// remoteManager.js
const axios = require('axios');
const { RemoteAgent } = require('./remoteAgent');

class RemoteMananger {
    constructor(app) {
        this.app = app;
        this.remotes = {};
    }

    // 测试连接是否通
    async ping(remoteId) {
        try {
            // 获取remote信息
            let remoteInfo = null;
            try {
                remoteInfo = await this.app.remote_db.getRemoteInfo(remoteId);
            } catch (error) {
                console.error('Get Remote Info Failed, Error: ', error);
                return { code: -1, msg: error };
            }

            // 访问remote通道，判断是否连同
            let url = `http://localhost:${remoteInfo.tunnel_src_port}/Ping`;
            const response = await axios.get(url);
            // console.log(response.data);

            // 更新连接状态
            return response.data;
        } catch (error) {
            return { code: -1, msg: error.message };
        }
    }

    // 连接远程服务器
    async connect(remoteId) {
        // 获取remoteId的信息
        let remoteInfo = null;
        try {
            remoteInfo = await this.app.remote_db.getRemoteInfo(remoteId);
        } catch (error) {
            console.error('Get Remote Info Failed, Error: ', error);
            return { code: -3, msg: error };
        }
        console.log('Connecting ssh remoteInfo =', remoteInfo);

        // 创建remoteAgent对象
        if (!this.remotes[remoteId]) {
            this.remotes[remoteId] = new RemoteAgent(this.app, remoteInfo);
        }
        let remote = this.remotes[remoteId];
        remote.config = remoteInfo;

        // 建立ssh通道并进行远程环境初始化
        let error_codes = [];
        if (remoteInfo.ssh_status === 0) {
            try {
                await remote.connect();
                await this.app.remote_db.updateRemote({ id: remoteId, ssh_status: 1 });
            } catch (error) {
                console.error('RemoteManager connect error = ', error);
                if (error.code == -1) {
                    return { code: -1, msg: 'SSH connection Error: ' + error.msg };
                } else {
                    error_codes.push(-1);
                }
            }
        }

        // 根据环境初始化的信息，建立tunnel
        try {
            if (!remote.local_server) {
                let tunnel_info = {
                    src_port: remoteInfo.tunnel_src_port,
                    dst_port: remoteInfo.tunnel_dst_port
                };
                await remote.createTunnel(tunnel_info);
            }
        } catch (error) {
            // console.error(error);
            await this.app.remote_db.updateRemote({ id: remoteId, server_status: 0 });
            return { code: -2, msg: 'Create http tunnel Error' };
        }

        // 访问接口Ping测试连接是否正常
        // let result = await this.ping(remoteId);
        // if (result.code != 0) {
        //     error_codes.push(-4);
        // }
        // await this.app.remote_db.updateRemote({ id: remoteId, server_status: result.code === 0 ? 1 : 0 });

        // 返回结果
        return { code: 0, msg: `Remote ${remoteId} Created OK!` };
    }

    // 断开远程服务器
    async disconnect(remoteId) {
        // 获取远程连接对象
        let remote = this.remotes[remoteId];
        if (!remote) {
            return { code: -1, msg: `Remote ${remoteId} not found!` };
        }

        // 关闭远程连接，包括ssh和tunnel通道
        let result = await remote.disconnect();
        let code = result.code;

        // 更新连接状态
        await this.app.remote_db.updateRemote({ id: remoteId, ssh_status: 0, server_status: 0 });

        return result;
    }

    // 远程执行命令
    async execute(remoteId, command) {
        console.log(`RemoteManager remoteId = ${remoteId} command = ${command}`);
        // 获取远程连接对象
        let remote = this.remotes[remoteId];
        if (!remote) {
            return { code: -1, msg: `Remote ${remoteId} not found!` };
        }

        // 调用远程ssh agent对象的执行命令行
        try {
            let result = await remote.executeCommand(command);
            return { code: result.code, msg: result.stdout };
        } catch (error) {
            // console.error('remoteManager execute error = ', error);
            if (!error.hasOwnProperty('code')) {
                console.error('检测到远程连接异常！', error);
                await this.app.remote_db.updateRemote({ id: remoteId, ssh_status: 0, server_status: 0 });
            }
            return { code: error.code, msg: error.stderr };
        }
    }

    // 执行远程脚本（脚本在远程机器上）
    async execScript(remoteId, script_path) {
        console.log(`RemoteManager execScript = ${remoteId} script_path = ${script_path}`);

        // 获取远程连接对象
        let remote = this.remotes[remoteId];
        if (!remote) {
            return { code: -1, msg: `Remote ${remoteId} not found!` };
        }

        // 调用远程ssh agent对象的执行命令行
        try {
            let result = await remote.execScript(script_path);
            return { code: result.code, msg: result.stdout };
        } catch (error) {
            // console.error('remoteManager execScript error = ', error);
            await this.app.remote_db.updateRemote({ id: remoteId, ssh_status: 0, server_status: 0 });
            return { code: -1, msg: 'remote execute script failed!' };
        }
    }

    // 在远程执行本地脚本（脚本在本机上）
    async execScriptFromLocal(remoteId, script_path) {
        console.log(`RemoteManager execScriptFromLocal = ${remoteId} script_path = ${script_path}`);

        // 获取远程连接对象
        let remote = this.remotes[remoteId];
        if (!remote) {
            return { code: -1, msg: `Remote ${remoteId} not found!` };
        }

        // 调用远程ssh agent对象的执行命令行
        try {
            let result = await remote.execScript(script_path);
            return { code: result.code, msg: result.stdout };
        } catch (error) {
            // console.error('remoteManager execScript error = ', error);
            await this.app.remote_db.updateRemote({ id: remoteId, ssh_status: 0, server_status: 0 });
            return { code: -1, msg: 'remote execute local script failed!' };
        }
    }

    // 上传文件到远程服务器
    async uploadFile(remoteId, localPath, remotePath) {
        console.log(`RemoteManager uploadFile: remoteId = ${remoteId} localPath = ${localPath}`);
        // 获取远程连接对象
        let remote = this.remotes[remoteId];
        if (!remote) {
            return { code: -1, msg: `Remote ${remoteId} not found!` };
        }

        // 调用远程ssh agent的上传文件方法
        try {
            if (await remote.uploadFile(localPath, remotePath)) {
                return { code: 0, msg: `Upload File ${localPath} OK!` };
            } else {
                return { code: -1, msg: `Upload File ${localPath} Failed!` };
            }
        } catch (error) {
            return { code: -1, msg: `Upload File ${localPath} Failed!` };
        }
    }

    // 关闭所有打开的资源以及数据库连接
    async close() {
        for (let remoteId in this.remotes) {
            let remote = this.remotes[remoteId];
            if (remote) {
                console.log(`## Close Remote Agent ${remoteId}...`);
                let code = -1;
                try {
                    // 退出的时候，关闭remote连接
                    let result = await remote.disconnect();
                    code = result.code;
                    console.log(`## Closed Remote Agent ${remoteId} OK!`);
                } catch (error) {
                    console.error(`## Failed to close Remote Agent ${remoteId}, Error: `, error);
                } finally {
                    // 更新连接状态
                    await this.app.remote_db.updateRemote({ id: remoteId, ssh_status: 0, server_status: 0 });
                }
            }
        }
    }

    // 判断remoteId是否已经连接
    async isSSHConnected(remoteId) {
        // 判断ssh连接是否在存在
        let remote = this.remotes[remoteId];
        if (!remote) {
            return false;
        }

        // 判断远程连接是否有问题
        let conntected = await remote.isSSHConnected();
        return conntected;
    }
}

module.exports = { RemoteMananger };
